package com.mspbots.ticketai.graderule;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.mspbots.ticketai.GradeRuleInterceptorAdapter;
import com.mspbots.ticketai.model.Ticket;
import com.mspbots.ticketai.model.TicketRule;
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Log4j2
@Service(value = "TEAM_MATCHING_POINT_RULE")
public class TeamMatchingRuleInterceptor extends GradeRuleInterceptorAdapter {

    private List<TeamMatchingParam> params;

    @Override
    public void prepare(TicketRule rule) {
        params = this.objectMapper.convertValue(rule.getParams(), new TypeReference<>() {
        });
    }

    @Override
    public void process(Ticket ticket) {
        AtomicInteger order = new AtomicInteger();
        Set<String> ticketTeamNames = new HashSet<>();
        if (ticket.getTeamRoles() != null) {
            Iterator<JsonNode> nodeJson = ticket.getTeamRoles().elements();
            while (nodeJson.hasNext()) {
                JsonNode node = nodeJson.next();
                if (!StringUtils.isEmpty(node.get("teamRole"))) {
                    ticketTeamNames.add(node.get("teamRole").get("name").asText());
                }
            }
        }
        if (!CollectionUtils.isEmpty(ticket.getMemberTeamNames())
                && !StringUtils.isEmpty(ticket.getIdentifier())
                && !CollectionUtils.isEmpty(ticketTeamNames)) {
            List<String> ticketTeamNameNews = ticketTeamNames.stream().map(String::toLowerCase).collect(Collectors.toList());
            params.stream().filter(p -> p.isSelected())
                    .forEach(item -> {
                        for (String n : ticket.getMemberTeamNames()) {
                            if (ticketTeamNameNews.contains(n.toLowerCase())) {
                                order.addAndGet(item.getPoints());
                                break;
                            }
                        }
                    });
        }
        ObjectNode itemsNode = this.objectMapper.createObjectNode();
        itemsNode.put("ticketTeamNames", CollectionUtils.isEmpty(ticketTeamNames) ? "" : String.join(", ", ticketTeamNames));
        itemsNode.put("userTeamNames", CollectionUtils.isEmpty(ticket.getMemberTeamNames()) ? "" : String.join(", ", ticket.getMemberTeamNames()));
        itemsNode.put("point", order.get());
        ObjectNode orderDetailNode = ticket.getOrderDetail() == null ? this.objectMapper.createObjectNode() : ticket.getOrderDetail().deepCopy();
        orderDetailNode.set("teamMatching", itemsNode);
        ticket.setOrderDetail(orderDetailNode);
        ticket.setOrder(ticket.getOrder() + order.get());
    }

    @Data
    private static class TeamMatchingParam {
        private Integer index;
        private Integer points;
        private String condition;
        private boolean selected;
    }
}
